home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / sys / unix / unixunix.c < prev   
Encoding:
C/C++ Source or Header  |  1993-08-01  |  7.7 KB  |  347 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)unixunix.c    3.1    90/22/02
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /* This file collects some Unix dependencies */
  6.  
  7. #include "hack.h"    /* mainly for index() which depends on BSD */
  8.  
  9. #include <errno.h>
  10. #include <sys/stat.h>
  11. #ifdef NO_FILE_LINKS
  12. #include <fcntl.h>
  13. #endif
  14. #include <signal.h>
  15. #if defined(BSD) || defined(ULTRIX)
  16. #include <sys/wait.h>
  17. #endif
  18.  
  19. #ifdef _M_UNIX
  20. extern void NDECL(sco_mapon);
  21. extern void NDECL(sco_mapoff);
  22. #endif
  23.  
  24. static struct stat buf, hbuf;
  25.  
  26. void
  27. gethdate(name) const char *name; {
  28. /* old version - for people short of space */
  29. /*
  30. /* register char *np;
  31. /*    if(stat(name, &hbuf))
  32. /*        error("Cannot get status of %s.",
  33. /*            (np = rindex(name, '/')) ? np+1 : name);
  34. /*
  35. /* version using PATH from: seismo!gregc@ucsf-cgl.ARPA (Greg Couch) */
  36.  
  37.  
  38. /*
  39.  * The problem with   #include    <sys/param.h>   is that this include file
  40.  * does not exist on all systems, and moreover, that it sometimes includes
  41.  * <sys/types.h> again, so that the compiler sees these typedefs twice.
  42.  */
  43. #define        MAXPATHLEN    1024
  44.  
  45. register const char *np, *path;
  46. char filename[MAXPATHLEN+1];
  47.     if (index(name, '/') != NULL || (path = getenv("PATH")) == NULL)
  48.         path = "";
  49.  
  50.     for (;;) {
  51.         if ((np = index(path, ':')) == NULL)
  52.             np = path + strlen(path);    /* point to end str */
  53.         if (np - path <= 1)            /* %% */
  54.             Strcpy(filename, name);
  55.         else {
  56.             (void) strncpy(filename, path, np - path);
  57.             filename[np - path] = '/';
  58.             Strcpy(filename + (np - path) + 1, name);
  59.         }
  60.         if (stat(filename, &hbuf) == 0)
  61.             return;
  62.         if (*np == '\0')
  63.             break;
  64.         path = np + 1;
  65.     }
  66. #if defined(BOS) && defined(NHSTDC)
  67. /*
  68.  *    This one is really **STUPID**.  I don't know why it's happening
  69.  *    as similar constructs work elsewhere, but...
  70.  */
  71.     if((np = rindex(name, '/')))
  72.          error("Cannot get status of %s.", np+1);
  73.     else error("Cannot get status of %s.", name);
  74. #else
  75.     error("Cannot get status of %s.",
  76.         (np = rindex(name, '/')) ? np+1 : name);
  77. #endif
  78. }
  79.  
  80. int
  81. uptodate(fd)
  82. int fd;
  83. {
  84.     if(fstat(fd, &buf)) {
  85.         pline("Cannot get status of saved level? ");
  86.         wait_synch();
  87.         return(0);
  88.     }
  89.     if(buf.st_mtime < hbuf.st_mtime) {
  90.         pline("Saved level is out of date. ");
  91.         wait_synch();
  92.         return(0);
  93.     }
  94.     return(1);
  95. }
  96.  
  97. /* see whether we should throw away this xlock file */
  98. static int
  99. veryold(fd)
  100. int fd;
  101. {
  102.     time_t date;
  103.  
  104.     if(fstat(fd, &buf)) return(0);            /* cannot get status */
  105. #ifndef INSURANCE
  106.     if(buf.st_size != sizeof(int)) return(0);    /* not an xlock file */
  107. #endif
  108. #ifdef BSD
  109.     (void) time((long *)(&date));
  110. #else
  111.     (void) time(&date);
  112. #endif
  113.     if(date - buf.st_mtime < 3L*24L*60L*60L) {    /* recent */
  114. #ifndef NETWORK
  115.         extern int errno;
  116. #endif
  117.         int lockedpid;    /* should be the same size as hackpid */
  118.  
  119.         if(read(fd, (genericptr_t)&lockedpid, sizeof(lockedpid)) !=
  120.             sizeof(lockedpid))
  121.             /* strange ... */
  122.             return(0);
  123.  
  124.         /* From: Rick Adams <seismo!rick>
  125.         /* This will work on 4.1cbsd, 4.2bsd and system 3? & 5.
  126.         /* It will do nothing on V7 or 4.1bsd. */
  127. #ifndef NETWORK
  128.         /* It will do a VERY BAD THING if the playground is shared
  129.            by more than one machine! -pem */
  130.           if(!(kill(lockedpid, 0) == -1 && errno == ESRCH))
  131. #endif
  132.             return(0);
  133.     }
  134.     (void) close(fd);
  135.     return(1);
  136. }
  137.  
  138. static int
  139. eraseoldlocks()
  140. {
  141.     register int i;
  142.  
  143.     /* cannot use maxledgerno() here, because we need to find a lock name
  144.      * before starting everything (including the dungeon initialization
  145.      * that sets astral_level, needed for maxledgerno()) up
  146.      */
  147.     for(i = 1; i <= MAXDUNGEON*MAXLEVEL + 1; i++) {
  148.         /* try to remove all */
  149.         set_levelfile_name(lock, i);
  150.         (void) unlink(lock);
  151.     }
  152.     set_levelfile_name(lock, 0);
  153.     if(unlink(lock)) return(0);            /* cannot remove it */
  154.     return(1);                    /* success! */
  155. }
  156.  
  157. void
  158. getlock()
  159. {
  160.     extern int errno;
  161.     register int i = 0, fd, c;
  162.  
  163. #ifdef TTY_GRAPHICS
  164.     /* idea from rpick%ucqais@uccba.uc.edu
  165.      * prevent automated rerolling of characters
  166.      * test input (fd0) so that tee'ing output to get a screen dump still
  167.      * works
  168.      * also incidentally prevents development of any hack-o-matic programs
  169.      */
  170.     /* added check for window-system type -dlc */
  171.     if (!strcmp(windowprocs.name, "tty"))
  172.         if (!isatty(0))
  173.         error("You must play from a terminal.");
  174. #endif
  175.  
  176.     /* we ignore QUIT and INT at this point */
  177.     if (!lock_file(HLOCK, 10)) {
  178.         wait_synch();
  179.         error("");
  180.     }
  181.  
  182.     regularize(lock);
  183.     set_levelfile_name(lock, 0);
  184.  
  185.     if(locknum) {
  186.         if(locknum > 25) locknum = 25;
  187.  
  188.         do {
  189.             lock[0] = 'a' + i++;
  190.  
  191.             if((fd = open(lock, 0)) == -1) {
  192.                 if(errno == ENOENT) goto gotlock; /* no such file */
  193.                 perror(lock);
  194.                 unlock_file(HLOCK);
  195.                 error("Cannot open %s", lock);
  196.             }
  197.  
  198.             if(veryold(fd) /* closes fd if true */
  199.                             && eraseoldlocks())
  200.                 goto gotlock;
  201.             (void) close(fd);
  202.         } while(i < locknum);
  203.  
  204.         unlock_file(HLOCK);
  205.         error("Too many hacks running now.");
  206.     } else {
  207.         if((fd = open(lock, 0)) == -1) {
  208.             if(errno == ENOENT) goto gotlock;    /* no such file */
  209.             perror(lock);
  210.             unlock_file(HLOCK);
  211.             error("Cannot open %s", lock);
  212.         }
  213.  
  214.         if(veryold(fd) /* closes fd if true */ && eraseoldlocks())
  215.             goto gotlock;
  216.         (void) close(fd);
  217.  
  218.         if(flags.window_inited) {
  219.             c = yn("There is already a game in progress under your name.  Destroy old game?");
  220.         } else {
  221.             (void) printf("\nThere is already a game in progress under your name.");
  222.             (void) printf("  Destroy old game? [yn] ");
  223.             (void) fflush(stdout);
  224.             c = getchar();
  225.             (void) putchar(c);
  226.             (void) fflush(stdout);
  227.             while (getchar() != '\n') ; /* eat rest of line and newline */
  228.         }
  229.         if(c == 'y' || c == 'Y')
  230.             if(eraseoldlocks())
  231.                 goto gotlock;
  232.             else {
  233.                 unlock_file(HLOCK);
  234.                 error("Couldn't destroy old game.");
  235.             }
  236.         else {
  237.             unlock_file(HLOCK);
  238.             error("");
  239.         }
  240.     }
  241.  
  242. gotlock:
  243.     fd = creat(lock, FCMASK);
  244.     unlock_file(HLOCK);
  245.     if(fd == -1) {
  246.         error("cannot creat lock file.");
  247.     } else {
  248.         if(write(fd, (genericptr_t) &hackpid, sizeof(hackpid))
  249.             != sizeof(hackpid)){
  250.             error("cannot write lock");
  251.         }
  252.         if(close(fd) == -1) {
  253.             error("cannot close lock");
  254.         }
  255.     }
  256. }    
  257.  
  258. void
  259. regularize(s)    /* normalize file name - we don't like .'s, /'s, spaces */
  260. register char *s;
  261. {
  262.     register char *lp;
  263. #if defined(SYSV) && !defined(AIX_31) && defined(COMPRESS)
  264.     int i;
  265. #endif
  266.  
  267.     while((lp=index(s, '.')) || (lp=index(s, '/')) || (lp=index(s,' ')))
  268.         *lp = '_';
  269. #if defined(SYSV) && !defined(AIX_31)
  270.     /* avoid problems with 14 character file name limit */
  271. # ifdef COMPRESS
  272.     /* leave room for .e from error and .Z from compress appended to
  273.      * save files */
  274. #  ifdef COMPRESS_EXTENSION
  275.     i = 12 - strlen(COMPRESS_EXTENSION);
  276. #  else
  277.     i = 10;        /* should never happen... */
  278. #  endif
  279.     if(strlen(s) > i)
  280.         s[i] = '\0';
  281. # else
  282.     if(strlen(s) > 11)
  283.         /* leave room for .nn appended to level files */
  284.         s[11] = '\0';
  285. # endif
  286. #endif
  287. }
  288.  
  289. #ifdef SHELL
  290. int
  291. dosh()
  292. {
  293.     register char *str;
  294.     if(child(0)) {
  295.         if(str = getenv("SHELL"))
  296.             (void) execl(str, str, NULL);
  297.         else
  298.             (void) execl("/bin/sh", "sh", NULL);
  299.         raw_print("sh: cannot execute.");
  300.         exit(1);
  301.     }
  302.     return 0;
  303. }
  304. #endif /* SHELL /**/
  305.  
  306. #if defined(SHELL) || defined(DEF_PAGER) || defined(DEF_MAILREADER)
  307. int
  308. child(wt)
  309. int wt;
  310. {
  311.     register int f;
  312.     suspend_nhwindows(NULL);    /* also calls end_screen() */
  313. #ifdef _M_UNIX
  314.     sco_mapon();
  315. #endif
  316.     if((f = fork()) == 0){        /* child */
  317.         (void) setgid(getgid());
  318.         (void) setuid(getuid());
  319. #ifdef CHDIR
  320.         (void) chdir(getenv("HOME"));
  321. #endif
  322.         return(1);
  323.     }
  324.     if(f == -1) {    /* cannot fork */
  325.         pline("Fork failed.  Try again.");
  326.         return(0);
  327.     }
  328.     /* fork succeeded; wait for child to exit */
  329.     (void) signal(SIGINT,SIG_IGN);
  330.     (void) signal(SIGQUIT,SIG_IGN);
  331.     (void) wait( (int *) 0);
  332. #ifdef _M_UNIX
  333.     sco_mapoff();
  334. #endif
  335.     (void) signal(SIGINT, (SIG_RET_TYPE) done1);
  336. #ifdef WIZARD
  337.     if(wizard) (void) signal(SIGQUIT,SIG_DFL);
  338. #endif
  339.     if(wt) {
  340.         raw_print("");
  341.         wait_synch();
  342.     }
  343.     resume_nhwindows();
  344.     return(0);
  345. }
  346. #endif
  347.